////////////////////////////////////////////////////////////////////////////////
/// @file CallpAsnTypes.cc
/// @brief ASN types for callp and layer 2
///
/// Related Files: The definitions are in CallpAsnTypes.h.
/// Other related files are:
///
/// Maintained by: LTE eNB Callp Application Team
///
/// Copyright(c) 2009-2010 Nanocell, All Rights Reserved
///
/// CONFIDENTIALITY AND RESTRICTED USE
///
/// This software, including any software of third parties embodied herein,
/// contains information and concepts which are confidential to Nanocell
/// and such third parties. This software is licensed for use
/// solely in accordance with the terms and conditions of the applicable
/// license agreement with Nanocell or its authorized distributor.
////////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <string>
#include <stdlib.h>
#include "netinet/in.h"
#include "CallpAsnTypes.h"
//#include "ConvertAsnEnum.h"

using namespace LteApp::R1;
using namespace std;


//////////////////////////////////////////////////////////////////////////////
/// UlSchConfig
//////////////////////////////////////////////////////////////////////////////
void UlSchConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== UlSchConfig ========" << endl;

    oss << "  isMaxHarqTxPresent_                : ";
    if (isMaxHarqTxPresent_)
    {
        oss << "true" << endl;
        oss << "  maxHarqTx_                         : " << maxHarqTx_ << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    oss << "  isPeriodicBsrTimerPresent_         : ";
    if (isPeriodicBsrTimerPresent_)
    {
        oss << "true" << endl;
        oss << "  periodicBsrTimer_                  : " << periodicBsrTimer_ << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    oss << "  retxBsrTimer_                      : " << retxBsrTimer_  << endl;

    oss << "  ttiBundling_                       : ";
    if (ttiBundling_)
    {
        oss << "true" << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// LongDrxCycleStartOffset
//////////////////////////////////////////////////////////////////////////////
void LongDrxCycleStartOffset::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== LongDrxCycleStartOffset ========" << endl;
    oss << "  choice_                            : " << choice_ << endl;

    outString += oss.str();
    oss.str("");
}

//////////////////////////////////////////////////////////////////////////////
/// ShortDrx
//////////////////////////////////////////////////////////////////////////////
void ShortDrx::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== ShortDrx ========" << endl;
    oss << "  shortDrxCycle_                     : " << shortDrxCycle_ << endl;
    oss << "  drxShortCycleTimer_                : " << drxShortCycleTimer_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// DrxConfig
//////////////////////////////////////////////////////////////////////////////
void DrxConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== DrxConfig ========" << endl;
    oss << "  onDurationTimer_                   : " << onDurationTimer_ << endl;
    oss << "  drxInactivityTimer_                : " << drxInactivityTimer_ << endl;
    oss << "  drxRetransmissionTimer_            : " << drxRetransmissionTimer_ << endl;

    outString += oss.str();
    oss.str("");

    longDrxCycleSartOffset_.debugDump(outString);

    oss << "  isShortDrxPresent_                 : ";
    if (isShortDrxPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        shortDrx_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// PhrConfig
//////////////////////////////////////////////////////////////////////////////
void PhrConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== PhrConfig ========" << endl;
    oss << "  periodicPhrTimer_                  : " << periodicPhrTimer_ << endl;
    oss << "  prohibitPhrTimer_                  : " << prohibitPhrTimer_ << endl;
    oss << "  dlPathlossChange_                  : " << dlPathlossChange_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// MacMainConfig
//////////////////////////////////////////////////////////////////////////////
void MacMainConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== MacMainConfig ========" << endl;

    oss << "  timeAlignmentTimerDedicated_       : " << timeAlignmentTimerDedicated_ << endl;

    oss.str("");

    oss << "  isUlSchConfigPresent_       : ";
    if (isUlSchConfigPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        ulSchConfig_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isDrxConfigPresent_                : ";
    if (isDrxConfigPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        drxConfig_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
    oss << "  drxConfigChoice_                   : " << drxConfigChoice_ << endl;

    oss << "  isPhrConfigPresent_                : ";
    if (isPhrConfigPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        phrConfig_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
    oss << "  phrConfigChoice_                   : " << phrConfigChoice_ << endl;

    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// PdschConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void PdschConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== PdschConfigDedicated ========" << endl;
    oss << "  pA_                                : " << pA_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// PucchConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void PucchConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== PucchConfigDedicated ========" << endl;

    oss << "  isTddAckNackFeedbackModePresent_   : ";
    if (isTddAckNackFeedbackModePresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        oss << "  tddAckNackFeedbackMode_            : " << tddAckNackFeedbackMode_ << endl;
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss << "  ackNackRepetionChoice_             : " << ackNackRepetionChoice_ << endl;
    outString += oss.str();
    ackNackRepetition_.debugDump(outString);

    outString += oss.str();
    oss.str("");
}

//////////////////////////////////////////////////////////////////////////////
/// AckNackRepetition
//////////////////////////////////////////////////////////////////////////////
void AckNackRepetition::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== AckNackRepetition ========" << endl;

    oss << "  repetitionFactor_                  : " << repetitionFactor_ << endl;
    oss << "  n1PucchAnReq_                      : " << n1PucchAnReq_ << endl;

    outString += oss.str();
    oss.str("");
}

//////////////////////////////////////////////////////////////////////////////
/// PuschConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void PuschConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== PuschConfigDedicated ========" << endl;
    oss << "  betaOffsetAckIndex_               : " << betaOffsetAckIndex_ << endl;
    oss << "  betaOffsetRiIndex_                : " << betaOffsetRiIndex_ << endl;
    oss << "  betaOffsetCqiIndex_               : " << betaOffsetCqiIndex_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// UplinkPowerControlDedicated
//////////////////////////////////////////////////////////////////////////////
void UplinkPowerControlDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== UplinkPowerControlDedicated ========" << endl;
    oss << "  p0UePusch_                         : " << p0UePusch_ << endl;
    oss << "  deltaMcsEnabled_                   : " << deltaMcsEnabled_ << endl;
    oss << "  accumulationEnabled_               : ";
    if (accumulationEnabled_)
    {
        oss << "true" << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    oss << "  p0UePucch_                         : " << p0UePucch_ << endl;
    oss << "  pSrsOffset_                        : " << pSrsOffset_ << endl;
    oss << "  filterCoefficient_                 : " << filterCoefficient_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// TpcIndex
//////////////////////////////////////////////////////////////////////////////
void TpcIndex::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== TpcIndex ========" << endl;
    oss << "  indexFormatChoice_                 : " << choice_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// TpcPdcchConfig
//////////////////////////////////////////////////////////////////////////////
void TpcPdcchConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== TpcPdcchConfig ========" << endl;
    oss << "  pdcchConfigurationChoice_          : " << choice_ << endl;
    oss << "  tpcRnti_                           : " << tpcRnti_ << endl;

    outString += oss.str();
    oss.str("");

    tpcIndex_.debugDump(outString);
}


//////////////////////////////////////////////////////////////////////////////
/// CqiFormatIndicatorPeriodic
//////////////////////////////////////////////////////////////////////////////
void CqiFormatIndicatorPeriodic::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== CqiFormatIndicatorPeriodic ========" << endl;
    oss << "  choice_                            : " << choice_ << endl;
    oss << "  subBandCqi_                        : " << subBandCqi_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// CqiReportPeriodic
//////////////////////////////////////////////////////////////////////////////
void CqiReportPeriodic::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== CqiReportPeriodic ========" << endl;
    oss << "  cqiPucchResourceIndex_             : " << cqiPucchResourceIndex_ << endl;
    oss << "  cqiPmiConfigIndex_                 : " << cqiPmiConfigIndex_ << endl;
    oss << "  isRiConfigIndexPresent_            : ";
    if (isRiConfigIndexPresent_)
    {
        oss << "true" << endl;
        oss << "  riConfigIndex_                     : " << riConfigIndex_ << endl;
    }
    else
    {
        oss << "false" << endl;
    }
    oss << "  simultaneousAckNackAndCqi_         : ";
    if (simultaneousAckNackAndCqi_)
    {
        oss << "true" << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    outString += oss.str();
    oss.str("");

    cqiFormatIndicatorPeriodic_.debugDump(outString);
}


//////////////////////////////////////////////////////////////////////////////
/// CqiReportConfig
//////////////////////////////////////////////////////////////////////////////
void CqiReportConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== CqiReportConfig ========" << endl;
    oss << "  isCqiRepModeAperiodicPresent_      : ";
    if (isCqiRepModeAperiodicPresent_)
    {
        oss << "true" << endl;
        oss << "  cqiRepModeAperiodic_               : " << cqiRepModeAperiodic_ << endl;
    }
    else
    {
        oss << "false" << endl;
    }
    oss << "  nomPdschRsEpreOffset_              : " << nomPdschRsEpreOffset_ << endl;
    oss << "  isCqiReportPeriodicPresent_        : ";
    if (isCqiReportPeriodicPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        oss << "  reptPeriodicChocie_                : " << reptPeriodicChocie_ << endl;
        outString += oss.str();
        cqiReportPeriodic_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// SoundingRsUlConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void SoundingRsUlConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== SoundingRsUlConfigDedicated ========" << endl;
    oss << "  srsBandwidth_                      : " << srsBandwidth_ << endl;
    oss << "  srsHoppingBandwitdh_               : " << srsHoppingBandwitdh_ << endl;
    oss << "  freqDomainPos_                     : " << freqDomainPos_ << endl;
    oss << "  duration_                          : ";
    if (duration_)
    {
        oss << "true" << endl;
    }
    else
    {
        oss << "false" << endl;
    }

    oss << "  srsConfigIndex_                    : " << srsConfigIndex_ << endl;
    oss << "  transmissionComb_                  : " << static_cast<uint16_t>(transmissionComb_) << endl;
    oss << "  cyclicShift_                       : " << cyclicShift_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// CodebookSubsetRestriction
//////////////////////////////////////////////////////////////////////////////
void CodebookSubsetRestriction::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== CodebookSubsetRestriction ========" << endl;
    oss << "  antennaChoice_                     : " << choice_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// AntennaInfoDedicated
//////////////////////////////////////////////////////////////////////////////
void AntennaInfoDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== AntennaInfoDedicated ========" << endl;
    oss << "  transmissionMode_                  : " << transmissionMode_ << endl;

    oss << "  isCodebookSubsetRestrictionPresent_: ";
    if (isCodebookSubsetRestrictionPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        codebookSubsetRestriction_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  ueTransmitAntennaSelectionChoice_  : " << choice_ << endl;
    oss << "  ueTransmitAntennaSelectionEnable_  : " << enable_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// AntennaInfo
//////////////////////////////////////////////////////////////////////////////
void AntennaInfo::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== AntennaInfo ========" << endl;
    outString += oss.str();
    oss.str("");

    antennaInfoDedicated_.debugDump(outString);
}


//////////////////////////////////////////////////////////////////////////////
/// SchedulingRequestConfig
//////////////////////////////////////////////////////////////////////////////
void SchedulingRequestConfig::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== SchedulingRequestConfig ========" << endl;
    oss << "  srPucchResourceIndex_              : " << srPucchResourceIndex_ << endl;
    oss << "  srConfigIndex_                     : " << srConfigIndex_ << endl;
    oss << "  dsrTransMax_                       : " << dsrTransMax_ << endl;

    outString += oss.str();
    oss.str("");
}

//////////////////////////////////////////////////////////////////////////////
/// CodebookSubsetRestrictionV920
//////////////////////////////////////////////////////////////////////////////
void CodebookSubsetRestrictionV920::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== CodebookSubsetRestrictionV920 ========" << endl;
    oss << "  CodebookSubsetRestrV920Choice          : " << choice_ << endl;

    outString += oss.str();
    oss.str("");
}

//////////////////////////////////////////////////////////////////////////////
/// PhysicalConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void PhysicalConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== PhysicalConfigDedicated ========" << endl;

    oss << "  isPdschConfigDedicatedPresent_     : ";
    if (isPdschConfigDedicatedPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        pdschConfigDedicated_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isPucchConfigDedPresent_           : ";
    if (isPucchConfigDedPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        pucchConfigDedicated_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isPuschConfigDedicatedPresent_     : ";
    if (isPuschConfigDedicatedPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        puschConfigDedicated_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isUplinkPowerCtrlDedPresent_       : ";
    if (isUplinkPowerCtrlDedPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        uplinkPowerControlDedicated_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isTpcPdcchConfigPucchPresent_      : ";
    if (isTpcPdcchConfigPucchPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        tpcPdcchConfigPucch_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isTpcPdcchConfigPuschPresent_      : ";
    if (isTpcPdcchConfigPuschPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        tpcPdcchConfigPusch_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isCqiReportPresent_                : ";
    if (isCqiReportConfigPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        cqiReportConfig_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");

    oss << "  isSoundingRsUlConfigDedPresent_    : ";
    if (isSoundingRsUlConfigDedPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        soundingRsUlConfigDedicated_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
    oss << "  soundingRsUlConfigDedChoice_       : " << soundingRsUlConfigDedChoice_ << endl;

    oss << "  isAntennaInfoPresent_              : ";
    if (isAntennaInfoPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        antennaInfo_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
    oss << "  antennaInfoChoice_                 : " << antennaInfoChoice_ << endl;

    oss << "  isSchedulingRequestConfigPresent_  : ";
    if (isSchedulingRequestConfigPresent_)
    {
        oss << "true" << endl;
        outString += oss.str();
        schedulingRequestConfig_.debugDump(outString);
    }
    else
    {
        oss << "false" << endl;
        outString += oss.str();
    }

    oss.str("");
    oss << "  schedReqConfigChoice_              : " << schedReqConfigChoice_ << endl;

    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// RachConfigDedicated
//////////////////////////////////////////////////////////////////////////////
void RachConfigDedicated::debugDump(std::string& outString) const
{
    ostringstream oss;

    oss << "======== RachConfigDedicated ========" << endl;
    oss << "  raPreambleIndex_                   : " << raPreambleIndex_ << endl;
    oss << "  raPrachMaskIndex_                  : " << raPrachMaskIndex_ << endl;

    outString += oss.str();
    oss.str("");
}


//////////////////////////////////////////////////////////////////////////////
/// EutranTraceId
//////////////////////////////////////////////////////////////////////////////
void EutranTraceId::reset()
{
    memset(&value_, 0, sizeof(value_));
}

uint64_t EutranTraceId::getEutranTraceId() const
{
    uint64_t traceId;

    memcpy((uint8_t *)&traceId, value_, sizeof(uint64_t));

    traceId = (((uint64_t)(ntohl((uint32_t)((traceId << 32) >> 32))) << 32)
               + (uint32_t)ntohl(((uint32_t)(traceId >> 32))));

    return traceId;
}

void EutranTraceId::getEutranTraceId(uint8_t traceId[6], uint8_t traceRecId[2]) const
{
    memcpy(traceId, &(value_[0]), 6);
    memcpy(traceRecId, &(value_[6]), 2);
}

void EutranTraceId::setEutranTraceId(uint64_t traceId)
{
    traceId = (((uint64_t)(ntohl((uint32_t)((traceId << 32) >> 32))) << 32)
               + (uint32_t)ntohl(((uint32_t)(traceId >> 32))));

    memcpy(value_, (uint8_t *)&traceId, sizeof(uint64_t));
}

void EutranTraceId::setEutranTraceId(uint8_t traceId[6], uint8_t traceRecId[2])
{
    memcpy(&(value_[0]), traceId, 6);
    memcpy(&(value_[6]), traceRecId, 2);
}


//////////////////////////////////////////////////////////////////////////////
/// TraceActivation
//////////////////////////////////////////////////////////////////////////////
bool TraceActivation::getS1TraceDepth(TraceDepth &traceDepth) const
{
    bool retCode = false;

    if (INTERFACE_TO_TRACE_S1 == (interfacesToTrace_ & INTERFACE_TO_TRACE_S1))
    {
        traceDepth = traceDepth_;
        retCode = true;
    }

    return retCode;
}

bool TraceActivation::getX2TraceDepth(TraceDepth &traceDepth) const
{
    bool retCode = false;

    if (INTERFACE_TO_TRACE_X2 == (interfacesToTrace_ & INTERFACE_TO_TRACE_X2))
    {
        traceDepth = traceDepth_;
        retCode = true;
    }

    return retCode;
}

bool TraceActivation::getUuTraceDepth(TraceDepth &traceDepth) const
{
    bool retCode = false;

    if (INTERFACE_TO_TRACE_UU == (interfacesToTrace_ & INTERFACE_TO_TRACE_UU))
    {
        traceDepth = traceDepth_;
        retCode = true;
    }

    return retCode;
}

void TraceActivation::setS1TraceDepth(const TraceDepth &traceDepth)
{
    interfacesToTrace_ |= INTERFACE_TO_TRACE_S1;
    traceDepth_ = traceDepth;
}

void TraceActivation::setX2TraceDepth(const TraceDepth &traceDepth)
{
    interfacesToTrace_ |= INTERFACE_TO_TRACE_X2;
    traceDepth_ = traceDepth;
}

void TraceActivation::setUuTraceDepth(const TraceDepth &traceDepth)
{
    interfacesToTrace_ |= INTERFACE_TO_TRACE_UU;
    traceDepth_ = traceDepth;
}

void PlmnIdType::reset()
{
    mcc1_ = mcc2_ = mcc3_ = 0;
    mnc1_ = mnc2_ = mnc3_ = 0;
}

bool PlmnIdType::convertPlmnIdToHexFormat(std::string& plmnIdString, uint32_t& plmnIdInHex)
{
    bool rc = true;
    uint32_t length = plmnIdString.length();

    if ((length > 6) || (length < 5))
    {
        plmnIdInHex = 0;
        rc = false;
    }
    else
    {
        // length = 6 or length = 5
        if (length == 5)
        {
            // padding "F" to the least significant digit of string
            plmnIdString += "F";
        }
        // convert string to Hex value
        plmnIdInHex = strtol (plmnIdString.c_str(), NULL, 16);
    }
    return rc;
}

bool UeEutraCapability::isUeFeatureSupported(UeFeature ueFeature, uint32_t featureGroupIndicators)
{
    bool result = false;
    if(ueFeature > MAX_UE_FEATURE)
    {
        return false;
    }

    switch(ueFeature)
    {
        case UE_FEATURE_BIT03:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT07) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT03) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT04:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT05) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT04) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT08:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT22) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT08) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT09:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT23) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT09) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT11:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT24) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT11) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT12:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT26) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT12) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT13:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT25) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT13) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT15:
        {
            result = (( (featureGroupIndicators << UE_FEATURE_BIT22) & 0x80000000 ) ||
                      ( (featureGroupIndicators << UE_FEATURE_BIT23) & 0x80000000 ) ||
                      ( (featureGroupIndicators << UE_FEATURE_BIT24) & 0x80000000 ) ||
                      ( (featureGroupIndicators << UE_FEATURE_BIT26) & 0x80000000 ) ) &&
                      ( (featureGroupIndicators << UE_FEATURE_BIT15) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT17:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT05) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT17) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT18:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT05) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT18) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT19:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT05) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT19) & 0x80000000 );
            break;
        }
        case UE_FEATURE_BIT27:
        {
            result = ( (featureGroupIndicators << UE_FEATURE_BIT08) & 0x80000000 ) &&
                     ( (featureGroupIndicators << UE_FEATURE_BIT27) & 0x80000000 );
            break;
        }
        default:
        {
            result = (featureGroupIndicators << ueFeature) & 0x80000000;
            break;
        }
    }

    return result;
}

GlobalEnbId EutranCgi::getGlobalEnbId()
{
     LteApp::R1::GlobalEnbId globalEnbId;
     LteApp::R1::EnbId enbId;

     enbId.choice_ = LteApp::R1::EnbId::MACRO_ENB_ID_CHOSEN;
     enbId.macroEnbId_ = (eutranCellId_ & 0x0FFFFF00)>>8;

     globalEnbId.plmnIdentity_ = plmnId_;
     globalEnbId.enbId_  = enbId;

     return globalEnbId;
}

std::ostream & operator<<(std::ostream &oss, const EutranCgi &ecgi)
{
	oss<<"ECGI: ";
	oss<<"PLMN ID: "<< ecgi.plmnId_.convertPlmnIdToUint32();
	oss<<"Eutran Cell ID: "<< ecgi.eutranCellId_<<endl;

	return oss;
}
